package com.evil.application.pojo.dto.es;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONUtil;
import co.elastic.clients.elasticsearch._types.aggregations.Aggregation;
import co.elastic.clients.elasticsearch._types.aggregations.CalendarInterval;
import co.elastic.clients.elasticsearch._types.aggregations.TermsAggregation;
import com.evil.common.es.dto.application.order.data.ESControlDataValueDTO;
import com.evil.common.es.util.ESFieldUtil;
import com.evil.common.family.enums.DateTypeEnum;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;

import java.util.HashMap;
import java.util.Map;

/**
 * @author liyang
 * @date 2023-08-08 15:49
 */
@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = true)
public class AggTerms extends Agg {

    public final static Integer TERMS_SIZE = 1000;

    private Terms terms;

    public AggTerms(String title) {
        super(title);
    }

    @Override
    public Aggregation.Builder.ContainerBuilder toAggregation() {
        // 时间格式化
        if (null != this.terms.dateType) {
            return this.aggDate(this.terms.field, this.terms.dateType);
        } else {
            return new Aggregation.Builder().terms(t -> {
                TermsAggregation.Builder builder = t.field(this.terms.field).missing(this.terms.missing);
                if (null != this.terms.size) {
                    builder.size(this.terms.size);
                }
                return builder;
            });
        }
    }

    private Aggregation.Builder.ContainerBuilder aggDate(String valueField, Integer dateType) {
        // 格式化需要去把 *.data_value.keyword 替换成 *.date
        String front = String.format("%s.%s", ESControlDataValueDTO.COL_DV, ESFieldUtil.KEYWORD);
        String valueFieldFinal = valueField.replace(front, ESControlDataValueDTO.COL_DATE);

        DateTypeEnum dateTypeEnum = DateTypeEnum.findById(dateType);
        CalendarInterval interval = switch (dateTypeEnum) {
            case TIME, DATE_SECOND, DATE_SECOND_RANGE -> CalendarInterval.Second;
            case MINUTE, DATE_MINUTE, DATE_MINUTE_RANGE -> CalendarInterval.Minute;
            case HOUR, DATE_HOUR, DATE_HOUR_RANGE -> CalendarInterval.Hour;
            case DATE, DATE_RANGE -> CalendarInterval.Day;
            case MONTH, MONTH_RANGE -> CalendarInterval.Month;
            case YEAR, YEAR_RANGE -> CalendarInterval.Year;
        };
        return new Aggregation.Builder().dateHistogram(e -> e.field(valueFieldFinal)
                .calendarInterval(interval).format(dateTypeEnum.getPattern()));
    }

    @Override
    public String toString() {
        HashMap<Object, Object> map = new HashMap<>();
        Map<String, Object> objMap = BeanUtil.beanToMap(this, true, false);
        map.put(this.getTitle(), objMap);
        return JSONUtil.toJsonStr(map);
    }

    @Data
    @AllArgsConstructor
    public static class Terms {

        private String field;
        private String missing;
        private Integer dateType;
        private Integer size;

        public Terms(String field) {
            this.field = field;
            this.missing = "";
        }

        public Terms(String field, String missing) {
            this.field = field;
            this.missing = missing;
        }

        public Terms(String field, Integer size) {
            this.field = field;
            this.missing = "";
            this.size = size;
        }

        @Override
        public String toString() {
            return JSONUtil.toJsonStr(this);
        }
    }
}
